#include <iostream>
#include <thread>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <cassert>
#include <cstdio> 

using namespace std;
// 如果多线程访问同一个全局变量，并对它进行数据计算，多线程之间会互相产生影响
// 加锁保护
// pthread_mutex_t mtx=PTHREAD_MUTEX_INITIALIZER; // pthread_mutex_t 就是原生线程库提供的一个数据类型
int tickets = 10000; // 在并发访问的时候，导致了数据不一致的问题 临界资源

#define THREAD_NUM 10

class ThreadData
{
public:
    ThreadData(const std::string &n,pthread_mutex_t *pm):tname(n), pmtx(pm)
    {}
public:
    std::string tname;
    pthread_mutex_t *pmtx;
};

void *getTickets(void *args)
{
    // int myerrno=errno;
    ThreadData *td = (ThreadData*)args;
    while(true)
    {
        // 抢票逻辑
        int n=pthread_mutex_lock(td->pmtx);
        assert(n==0);
        // 临界区
        if(tickets > 0) // 1. 判断的本质也是计算的一种
        {
            usleep(rand()%1500); //模拟实际抢票花费的时间
            printf("%s: %d\n", td->tname.c_str(), tickets);
            tickets--; // 2. 也有可能出现问题
            n=pthread_mutex_unlock(td->pmtx);
            assert(n==0);
        }
        //解锁
        else
        {
            n=pthread_mutex_unlock(td->pmtx);
            assert(n==0);
            break; //票被抢完了
        }

        // 抢票后的后续动作
        usleep(rand()%2000);
        // errno=myerrno;
    }
    delete td;
    return nullptr;
}

int main()
{
    time_t start=time(nullptr);
    pthread_mutex_t mtx;
    pthread_mutex_init(&mtx, nullptr);

    srand((unsigned long)time(nullptr) ^ getpid() ^ 0x147);
    pthread_t t[THREAD_NUM];

    // 多线程抢票的逻辑:
    for(int i = 0; i < THREAD_NUM; i++)
    {
        std::string name = "thread ";
        name += std::to_string(i+1);
        ThreadData *td = new ThreadData(name, &mtx);
        pthread_create(t + i, nullptr, getTickets, (void*)td);
    }

    for(int i = 0; i < THREAD_NUM; i++)
    {
        pthread_join(t[i], nullptr);
    }

    pthread_mutex_destroy(&mtx);

    time_t end=time(nullptr);

    cout << "case: " << (int)(end-start) << "s" << endl;
}

// void fun()
// {
//     while(true)
//     {
//         cout << "hello new thread" << endl;
//         sleep(1);
//     }
// }

// int main()
// {
//     std::thread t(fun);
//     std::thread t1(fun);
//     std::thread t2(fun);
//     std::thread t3(fun);
//     std::thread t4(fun);

//     while(true)
//     {
//         cout << "hello new thread" << endl;
//         sleep(1);
//     }

//     t.join();
// }

// // _ _thread: 修饰全局变量，结果就是让每一个线程各自拥有一个全局变量 —— 线程的局部存储
// __thread int g_val=0;

// // 1. 哪个线程先运行跟调度器有关
// // 2. 线程一旦异常，就有可能导致整个进程整体退出
// // 3. 线程的输入和返回值
// // 4. 线程异常退出的理解
// void *threadRoutine(void *args)
// {
//     // pthread_detach(pthread_self());

//     // sleep(5);
//     // execl("/bin/ls", "ls", nullptr);

//     while(true)
//     {
//         cout << (char*)args << " : " << g_val << " &: " << &g_val << endl;
//         g_val++;
//         sleep(1);
//         // int a=10;
//         // a/=0;
//         break;
//     }
//     pthread_exit((void*)11);

//     // int i=0;
//     // // int *data=new int[10];
//     // while(true)
//     // {
//     //     cout << "新线程: " << (char*)args << " running..." << pthread_self() << endl; 
//     //     sleep(1);
//     //     // data[i]=i; 
//     //     // if(i++==3) break;
//     //     // int a=100;
//     //     // a/=0;
//     // }
//     // pthread_exit((void*)13);
//     // exit(10); //不要调用exit，exit是终止进程的
//     // cout << "new thread quit..." << endl;
//     // return (void*)data;
//     // return (void*)10; //一般返回给main thread，main通过pthread_join获取
// }

// int main()
// {
//     // 因为我们目前用的不是Linux自带的创建线程的接口，我们用的是pthread库中的接口！
//     pthread_t tid; // 本质是一个地址！
//     pthread_create(&tid, nullptr, threadRoutine, (void *)"thread 1");

//     while(true)
//     {
//         cout << "main thread" << " : " << g_val << " &: " << &g_val << endl;
//         sleep(1);
//         break;
//     }
//     int n=pthread_join(tid, nullptr);
//     cout << "n: " << n << " errstring: " << strerror(n) << endl;

//     // printf("%lu, %p\n", tid, tid);
//     // int count=0;
//     // while(true)
//     // {
//     //     cout << "main线程: " << " running... main tid: " << pthread_self() << endl;
//     //     sleep(1);
//     //     count++;
//     //     if(count>=5) break;
//     // }
//     // pthread_cancel(tid);
//     // cout << "pthread cancel: " << tid << endl;

//     // int* ret=nullptr;
//     // pthread_join(tid, (void**)&ret); //默认会阻塞等待新线程退出

//     // 1.线程被取消，join时，退出码是-1
//     // PTHREAD_CANCELED;
//     // cout << "main thread wait done... main quit: new thread quit: " << (long long)ret << "\n";
//     // sleep(5);
//     // for(int i=0; i<10; i++)
//     // {
//     //     cout << ret[i] << endl;
//     // }

//     // 3. 线程在创建并执行时，线程也是需要进行等待的
//     // 如果主进程不等待，就会引起类似于进程的僵尸问题，导致内存泄漏
//     // while(true)
//     // {
//     //     cout << "main线程: " << " running..." << endl;
//     //     sleep(1);
//     // }
//     return 0;
// }